package org.streets.database.internal;

import java.beans.PropertyVetoException;
import java.sql.SQLException;

import javax.naming.NamingException;
import javax.sql.DataSource;

import org.slf4j.Logger;
import org.streets.commons.util.JNDIUtils;
import org.streets.database.ConnectionConfigurer;
import org.streets.database.SQLConnectionSource;
import org.streets.database.SQLNestedException;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.mchange.v2.c3p0.PooledDataSource;

public class PooledConnectionSourceImpl implements SQLConnectionSource {
	
	final DataSource ds; 
	final Logger logger;
	
	public PooledConnectionSourceImpl(ConnectionConfigurer cc, Logger logger,
			int minPoolSize,
			int maxPoolSize,
			int increment,
			int maxStatements,
			int maxIdleTime) {
	 	
		this.logger = logger;
		Object t_ds	= null;	
		// use jndi first
		if (cc.getJNDI() != null) {			
			try {
				t_ds = JNDIUtils.lookup(cc.getJNDI());
			} catch (NamingException ex ) {
				logger.warn("Could not find JNDI Object in loacation ["+cc.getJNDI()+"]"); 
			}
				
			if (t_ds != null) {
				// make sure it's a c3p0 PooledDataSource 
				if ( t_ds instanceof PooledDataSource) { 
					PooledDataSource pds = (PooledDataSource) t_ds; 
					try {
						logger.info("num_connections: " + pds.getNumConnectionsDefaultUser()); 
						logger.info("num_busy_connections: " + pds.getNumBusyConnectionsDefaultUser()); 
						logger.info("num_idle_connections: " + pds.getNumIdleConnectionsDefaultUser()); 
					} catch (SQLException ex) {
						// Do nothing.
					}
				} else {
					logger.warn("Not a c3p0 PooledDataSource!");					
				}
			}
		}
		// Use driver datasource
		if (t_ds == null && cc.getDriverName() != null && cc.getUrl() != null) {
			//ds = new ConnectionDataSource(config);
			ComboPooledDataSource cpds = new ComboPooledDataSource(); 
			try {
				cpds.setDriverClass(cc.getDriverName());
			} catch (PropertyVetoException e) {
				throw new SQLNestedException("Error loading driver: "+cc.getDriverName());				
			} //loads the jdbc driver 
			cpds.setJdbcUrl(cc.getUrl()); 
			cpds.setUser(cc.getUser()); 
			cpds.setPassword(cc.getPassword()); // the settings below are optional -- c3p0 can work with defaults 
			cpds.setMinPoolSize(minPoolSize); 
			cpds.setMaxPoolSize(maxPoolSize); 
			cpds.setAcquireIncrement(increment); 
			cpds.setMaxStatements(maxStatements);
			cpds.setMaxIdleTime(maxIdleTime);
			//cpds.setCheckoutTimeout(timeout);
			t_ds = cpds;
		}
		ds = (DataSource)t_ds;
	}
	
	public DataSource getDataSource() {
		return ds;
	}
	
	public void shutdown() {

		try {
			if (ds instanceof PooledDataSource) {
				((PooledDataSource)ds).close();
				logger.info("c3p0 datasource closed successfully ");
			}								
		} catch (SQLException ex) {
			logger.error("Error occurs when close c3p0 datasource", ex);
		}
	}
}
